﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Controls.Maps;
using System.Device.Location;
using Microsoft.Phone.Tasks;
using unifiqAnthony.GeocodeService;
using System.Windows.Media;
using DeepForest.Phone.Assets.Tools;
using System.IO;
using System.Windows.Media.Imaging;
using System.Net;

namespace unifiqAnthony
{
    public partial class ListingFunction : PhoneApplicationPage
    {
        CameraCaptureTask cameraCaptureTask;
        GeoCoordinateWatcher watcher;
        internal const string id = "Aggp0yd8miqzaqQrXChtjs8v2m4nlHd3lFn06-W9gu7ZI4KBhTzUddWbVjayXfTV"; //Bing key
        double currentLat = 0;
        double currentLong = 0;
        Boolean bShow = false;
        MapLayer pinLayer = new MapLayer();
        MapLayer NTUCpinLayer = new MapLayer();
        MapLayer ShopNSavepinLayer = new MapLayer();
        Supermart[] supermartLocations = new Supermart[21];
        unifiqAnthony.GeocodeService.Location listLoc = new unifiqAnthony.GeocodeService.Location();

        List<SupermartDistance> supermartDistance = new List<SupermartDistance>();

        UnifiqSvc.Listing listing = null;
        List<byte[]> byteList = null;

        public ListingFunction()
        {
            InitializeComponent();
            #region initialise the data into supermartLocations array

            //ntuc
            supermartLocations[0] = new Supermart("Blk 215 , Ang Mo Kio Ave 1 , #01-877, SINGAPORE 560215", 1.366746, 103.841615);
            supermartLocations[1] = new Supermart("Blk 712 , ANG MO KIO AVE 6 , #01-4056, SINGAPORE 560712", 1.371428, 103.847103);
            supermartLocations[2] = new Supermart("53 , Ang Mo Kio Ave 3 , #B2-26, Ang Mo Kio Hub ,SINGAPORE 569933", 1.36928, 103.848437);
            supermartLocations[3] = new Supermart("Blk 2761 , Ang Mo Kio Ave 5 , SINGAPORE 569866", 1.378994, 103.836168);
            supermartLocations[4] = new Supermart("Blk A , 2 ANG MO KIO DRIVE , #01-12, SINGAPORE 567720", 1.37775, 103.85536);
            supermartLocations[5] = new Supermart("Blk 510 , Bishan Street 13 , #01-520, SINGAPORE 570510", 1.348631, 103.849885);
            supermartLocations[6] = new Supermart("Blk 279 , Bishan Street 24 , #01-62/64, SINGAPORE 570279", 1.357517, 103.844087);
            supermartLocations[7] = new Supermart("9 , Bishan Place , #B1-01, Junction 8 Shopping Centre ,SINGAPORE 579837", 1.350529, 103.848437);
            //shop n save
            supermartLocations[8] = new Supermart("Blk 468B Admiralty Drive #01-29 S(752468)", 1.450182, 103.81415);
            supermartLocations[9] = new Supermart("Blk 181 Ang Mo Kio Avenue 5 #01-2932 S(560181)", 1.376788, 103.837013);
            supermartLocations[10] = new Supermart("Blk 161 Ang Mo Kio Avenue 4 #01-504 S(560161)", 1.374125, 103.839812);
            supermartLocations[11] = new Supermart("Blk 525 Ang Mo Kio Avenue 10 #01-2401/2403/2405 S(560525)", 1.372571, 103.853599);
            supermartLocations[12] = new Supermart("Blk 316B Ang Mo Kio Street 31 #01-11 S(563316)", 1.364831, 103.847772);
            //add the markers on the map
            AddPushpinsOnMap();
            bShow = false;
            #endregion
            if (watcher == null)
            {
                watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default);
                watcher.MovementThreshold = 20;
                watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged); //event occurs when position change
            }
            //watcher.Start();

            cameraCaptureTask = new CameraCaptureTask();
            cameraCaptureTask.Completed += new EventHandler<PhotoResult>(cameraCaptureTask_Completed);
        }

        void cameraCaptureTask_Completed(object sender, PhotoResult e)
        {
            if (e.TaskResult == TaskResult.OK)
            {
                MessageBox.Show(e.ChosenPhoto.Length.ToString());
            }
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            // Show Loading Screen
            tb_loading.Text = "Finding Location on Map";
            progressOverlay.Show();

            // Populate Fields
            loadData();

            String address = listing.blkNo + " " + listing.stName + " " + listing.stNo;

            LoadLocations(address);
        }

        void loadData()
        {
            var obj = App.Current as App;

            
            // Load Photos
            byteList = obj.byteList;

            int insCount = 1;
            foreach (byte[] x in byteList)
            {
                System.Diagnostics.Debug.WriteLine(x==null);
                
                if (x != null)
                {
                    Image img;
                    if (insCount == 1)
                    {
                        img = image1;
                        insCount++;
                    }
                    else if (insCount == 2)
                    {
                        img = image2;
                        insCount++;
                    }
                    else
                    {
                        img = image3;
                    }

                    BitmapImage bmp = new BitmapImage();
                    bmp.SetSource(new MemoryStream(x));

                    //bmp.SetSource(ms);
                    img.Source = bmp;
                }
                
                 
            }
            

            // Get Listing Details
            UnifiqSvc.Listing l = obj.listing;
            this.listing = l;

            string msg = "";
            if (NavigationContext.QueryString.TryGetValue("msg", out msg))
                textBlock1.Text = msg;
            int uid;

            uid = l.uid;
            tb_stName.Text = l.stName;
            tb_stNo.Text = l.stNo;
            tb_blkNo.Text = l.blkNo;
            tb_doorNo.Text = l.doorNo;
            tb_apptNo.Text = l.apptNo;
            tb_zipCode.Text = l.zipCode;
            tb_bldngName.Text = l.bldngName;
            tb_contactNo.Text = l.contactNo;
            tb_desc.Text = l.description;
            tb_fullName.Text = l.contactName;
            tb_noOfTenants.Text = l.noOfTenants.ToString();
            tb_fee.Text = l.fee.ToString();
        }

        private void LoadAddressPushpin(double lat, double lon)
        {
            System.Diagnostics.Debug.WriteLine("Execute: " + lat + ", " + lon);
            Pushpin pin = new Pushpin();
            GeoCoordinate geo = new GeoCoordinate(lat, lon);

            Map.ZoomLevel = 17;
            Map.Center = geo;

            pin.Location = geo;
            pin.Template = this.Resources["listingPin"] as ControlTemplate;
            Map.Children.Add(pin);

            /*
            System.Windows.Point p =  new System.Windows.Point(lat, lon);
            GeoCoordinate geo = new GeoCoordinate(lat, lon);
            geo = Map.ViewportPointToLocation(p);
            Map.ZoomLevel = 17;
            Map.Center = geo;
            //---create a new pushpin---
            Pushpin pin = new Pushpin();

            //---set the location for the pushpin---
            pin.Location = geo;

            pin.Template = this.Resources["ImagePin"] as ControlTemplate; //Control template for pushpin
            
            //---add the pushpin to the map---
            Map.Children.Add(pin);
             */
        }

        private void LoadLocations(string address)
        {
            GeocodeServiceClient geocodeService = new GeocodeService.GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
            GeocodeRequest geocodeRequest = new GeocodeRequest();
            {  
                
                geocodeRequest.Credentials = new unifiqAnthony.GeocodeService.Credentials() { ApplicationId = id };
                geocodeRequest.Query = "singapore "+ address;//"14820 NE 36th st redmond, wa 98052";//address;
                System.Diagnostics.Debug.WriteLine(geocodeRequest.Query);
                geocodeRequest.Options = new GeocodeOptions() { Filters = new System.Collections.ObjectModel.ObservableCollection<FilterBase>() };
            };
            geocodeRequest.Options.Filters.Add(new ConfidenceFilter() { MinimumConfidence = Confidence.Low });
            geocodeService.GeocodeAsync(geocodeRequest);

            // 
            geocodeService.GeocodeCompleted += (sender, e) => geoCode_GeocodeCompleted(sender, e);
        }

        /**
         * Methods called when the research is completed by the service 
         * 
         * */
        void geoCode_GeocodeCompleted(object sender, GeocodeService.GeocodeCompletedEventArgs e)
        {
            System.Text.StringBuilder result = new System.Text.StringBuilder();

            if (e.Result.Results.Count > 0)
            {
                GeocodeResult svcResult = e.Result.Results[0];

                // The service returns a list of locations. We will display each of them
                //foreach (unifiqAnthony.GeocodeService.Location loc in svcResult.Locations.ToList())
                ///{
                    unifiqAnthony.GeocodeService.Location loc = svcResult.Locations.ToList().First();
                    result.Append(loc.Latitude).Append(' ');
                    result.Append(loc.Longitude).Append('\n');
                    System.Diagnostics.Debug.WriteLine(loc.Latitude);
                    System.Diagnostics.Debug.WriteLine(loc.Longitude);
                    System.Diagnostics.Debug.WriteLine(svcResult.Locations.ToList().Count);
                    LoadAddressPushpin(loc.Latitude,loc.Longitude);
                    listing.lat = loc.Latitude;
                    listing.lon = loc.Longitude;
                    
                    //Hide Loading Screen
                    progressOverlay.Hide();
                //}
            }
            else
            {
                result.Append("No location found");
                NotificationTool.Show(
                "No Location Found",
                "Address may be invalid, or there is a server error. Please try again.",
                new NotificationAction("Ok", () => { NavigationService.GoBack();}));
            }
            //tb_desc.Text = result.ToString();
        }

        private readonly CredentialsProvider _credentialsProvider = new ApplicationIdCredentialsProvider(id);

        public CredentialsProvider CredentialsProvider
        {
            get { return _credentialsProvider; }
        }

        void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            //when coordinates are found, get the current location coordinate centered on the map
            this.Map.Center = new GeoCoordinate(e.Position.Location.Latitude, e.Position.Location.Longitude);
            // bug fix for Microsoft's location service default location
            if (e.Position.Location.Latitude == 47.64483)
            {
                this.Map.Center = new GeoCoordinate(1.358751, 103.844624);
            }
            if (this.Map.Children.Count != 0)
            {
                var pushpin = Map.Children.FirstOrDefault(p => (p.GetType() == typeof(Pushpin)));
                if (pushpin != null)
                {
                    this.Map.Children.Remove(pushpin);
                }
            }

            //initialise pushpin object, retrieve currentlocation coordinates and set it on the map//

            Pushpin locationPushpin = new Pushpin();
            locationPushpin.Tag = "CurrentLocation";
            locationPushpin.Template = this.Resources["ImagePin"] as ControlTemplate; //Control template for pushpin
            //current location happen to be at Microsoft's location, fix it to the Center initialised (Singapore's coordinate)
            if (e.Position.Location.Latitude == 47.64483)
            {
                locationPushpin.Location = this.Map.Center;
                currentLat = this.Map.Center.Latitude;
                currentLong = this.Map.Center.Longitude;
                this.Map.Children.Add(locationPushpin);
                this.Map.SetView(this.Map.Center, 10.5);
            } //end of bug fix

            else
            {
                locationPushpin.Location = watcher.Position.Location;
                currentLat = watcher.Position.Location.Latitude;
                currentLong = watcher.Position.Location.Longitude;
                this.Map.Children.Add(locationPushpin);
                this.Map.SetView(watcher.Position.Location, 15.0);
            }
        }

        private void AddPushpinsOnMap()
        {
            int i = 0;
            foreach (Supermart c in supermartLocations)
            {//ntuc

                if (i < 8)
                {
                    Pushpin locationPushpin = new Pushpin();
                    locationPushpin.Tag = "NTUCLocation";
                    if (c != null)
                    {
                        GeoCoordinate supermartLatLong = new GeoCoordinate(c.lat, c.longt);
                        locationPushpin.Location = supermartLatLong;
                        locationPushpin.Template = this.Resources["ImagePin2"] as ControlTemplate;
                        NTUCpinLayer.Children.Add(locationPushpin);
                    }
                }
                //shop nsave
                if (i >= 8 && i < 13)
                {
                    Pushpin locationPushpin = new Pushpin();
                    locationPushpin.Tag = "ShopNSaveLocation";
                    if (c != null)
                    {
                        GeoCoordinate supermartLatLong = new GeoCoordinate(c.lat, c.longt);
                        locationPushpin.Location = supermartLatLong;
                        locationPushpin.Template = this.Resources["ImagePin3"] as ControlTemplate;
                        ShopNSavepinLayer.Children.Add(locationPushpin);
                    }
                }
                i++;
            }
        }

        private void AppBarShowAll_Click(object sender, EventArgs e)
        {
            //show all supermart
            if (bShow == false)
            {
                this.Map.Children.Add(NTUCpinLayer);
                this.Map.Children.Add(ShopNSavepinLayer);
                bShow = true;
            }
            else
            {
                //this.Map.Children.Remove(pinLayer);
                this.Map.Children.Remove(NTUCpinLayer);
                this.Map.Children.Remove(ShopNSavepinLayer);
                bShow = false;
            }
        }

        private void AppBarNTUC_Click(object sender, EventArgs e)
        {
            //show NTUC
            if (bShow == false)
            {
                this.Map.Children.Add(NTUCpinLayer);
                bShow = true;
            }
            else
            {
                this.Map.Children.Remove(NTUCpinLayer);
                bShow = false;
            }
        }

        private void AppBarShopNSave_Click(object sender, EventArgs e)
        {
            //show Shop NSave
            if (bShow == false)
            {
                this.Map.Children.Add(ShopNSavepinLayer);
                bShow = true;
            }
            else
            {
                this.Map.Children.Remove(ShopNSavepinLayer);
                bShow = false;
            }
        }

        private void AppBarShowNearest_Click(object sender, EventArgs e)
        {//show nearest supermart
            foreach (Supermart supermartLocation in supermartLocations)
            {
                if (supermartLocation != null)
                {
                    if (currentLat != 0 && currentLong != 0)
                    {
                        supermartDistance.Add(new SupermartDistance(supermartLocation.name, supermartLocation.lat, supermartLocation.longt, GetDistanceBetweenPoints(currentLat, currentLong, supermartLocation)));
                    }
                }
            }
            //sort the distance calculated between current and nearest clinis location, arrange from ascending
            List<SupermartDistance> sortedList = supermartDistance.OrderBy(cl => cl.DistanceFromCurrentLocation1).ToList();
            MessageBoxResult m = MessageBox.Show(sortedList[0].name, "To Route to this supermarket", MessageBoxButton.OKCancel); //and then display info of the nearest supermart
            if (m == MessageBoxResult.OK)
            {
                RouteTo();
            }
        }

        //method to calculate distance between current location and each supermarket
        public double GetDistanceBetweenPoints(double currentLat, double currentLong, Supermart supermarketLocation)
        {
            double lat2 = supermarketLocation.lat;
            double long2 = supermarketLocation.longt;
            double distance = 0;
            double dLat = (lat2 - currentLat) / 180 * Math.PI;
            double dLong = (long2 - currentLong) / 180 * Math.PI;
            double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2)
            + Math.Cos(lat2) * Math.Sin(dLong / 2) * Math.Sin(dLong / 2);
            double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
            //Calculate radius of earth
            // assume any of the two points.
            double radiusE = 6378135; // Equatorial radius, in metres
            double radiusP = 6356750; // Polar Radius
            //Numerator part of function
            double nr = Math.Pow(radiusE * radiusP * Math.Cos(currentLat / 180 * Math.PI), 2);
            //Denominator part of the function
            double dr = Math.Pow(radiusE * Math.Cos(currentLat / 180 * Math.PI), 2)
            + Math.Pow(radiusP * Math.Sin(currentLat / 180 * Math.PI), 2);
            double radius = Math.Sqrt(nr / dr);
            //Calaculate distance in metres.
            distance = radius * c;
            return distance;
        }

        private void RouteTo()
        {
            //route to the nearest supermart from current position
            foreach (Supermart supermartLocation in supermartLocations)
            {
                if (supermartLocation != null)
                {
                    if (currentLat != 0 && currentLong != 0)
                    {
                        supermartDistance.Add(new SupermartDistance(supermartLocation.name, supermartLocation.lat, supermartLocation.longt, GetDistanceBetweenPoints(currentLat, currentLong, supermartLocation)));
                    }
                }
            }
            //sort the distance calculated between current and nearest supermart location, arrange from ascending
            //get shortest route to find nearest supermart coordinate
            List<SupermartDistance> sortedList = supermartDistance.OrderBy(cl => cl.DistanceFromCurrentLocation1).ToList();
            //and pass coordinates of nearestsupermart and current location to BingMapsDirectionTask to provide direction
            BingMapsDirectionsTask getDirection = new BingMapsDirectionsTask();

            getDirection.Start = new LabeledMapLocation("Current Location", new GeoCoordinate(currentLat, currentLong));
            getDirection.End = new LabeledMapLocation(sortedList[0].name, new GeoCoordinate(sortedList[0].lat, sortedList[0].longt));
            //sortedList[0] is the 1st item in arraylist, with the shortest distance from currentlocation
            //show directions
            getDirection.Show();
        }

        private void btn_post_Click(object sender, RoutedEventArgs e)
        {
            // Show Loading Screen
            tb_loading.Text = "Posting in Progress";
            progressOverlay.Show();

            // Store bytes to Listing obj
            int count = 1;
            foreach (byte[] x in byteList)
            {
                if (x != null)
                {
                    if(count==1)
                    {
                        listing.img1 = x;
                    }
                    else if(count==2)
                    {
                        listing.img2 = x;
                    }
                    else if(count==3)
                    {
                        listing.img3 = x;
                    }
                    count++;
                }

            }
            
            UnifiqSvc.Listing asd = new UnifiqSvc.Listing();

            UnifiqSvc.ServiceSoapClient dbSvc = new UnifiqSvc.ServiceSoapClient();
            dbSvc.insertListingCompleted += new EventHandler<UnifiqSvc.insertListingCompletedEventArgs>(dbSvc_insertListingCompleted);
            dbSvc.insertListingAsync(listing);

        }

        void dbSvc_insertListingCompleted(object sender, UnifiqSvc.insertListingCompletedEventArgs e)
        {
            // Hide Loading Screen
            progressOverlay.Hide();

            bool suc = e.Result;

            System.Diagnostics.Debug.WriteLine(listing.ToString());

            if (suc)
            {
                NotificationTool.Show(
                "Success",
                "Your listing is successfully posted!",
                new NotificationAction("OK", () => { NavigationService.Navigate(new Uri("/ListingMain.xaml", UriKind.Relative)); }));
            }
            else    
            {
                NotificationTool.Show(
                "Posting failed",
                "An error has occured; " + e.Error + "\n Please contact the Unifiq Team about this error",
                new NotificationAction("Ok", () => { }));
            }

        }

        void previewImage(int pos)
        {
            NavigationService.Navigate(new Uri("/ImagePreview.xaml?pos=" + pos, UriKind.Relative));
        }

        private void btn_image1_Click(object sender, RoutedEventArgs e)
        {
            if (image1.Source != null)
            {
                previewImage(1);
            }
            
        }

        private void btn_image2_Click(object sender, RoutedEventArgs e)
        {
            if (image2.Source != null)
            {
                previewImage(2);
            }
        }

        private void btn_image3_Click(object sender, RoutedEventArgs e)
        {
            //System.Diagnostics.Debug.WriteLine(image1.Source==null);
            
            if (image3.Source != null)
            {
                previewImage(3);
            }
        }

    }
}